﻿using System;
using System.Linq;
using NDBGen.Descriptors.Columns.Tokens;

namespace NDBGen.Descriptors.Columns.DataTypes
{
    [ColumnDataTypeDescriptor(DATATYPE_FILTER)]
    public sealed class StandardDataTypeDescriptor : ColumnDataTypeDescriptorBase
    {
        private const DataType DATATYPE_FILTER =
            DataType.Bit |
            DataType.TinyInt |
            DataType.SmallInt |
            DataType.Int |
            DataType.BigInt |
            DataType.Float |
            DataType.Decimal |
            DataType.Date |
            DataType.DateTime |
            DataType.DateTime2 |
            DataType.SmallDateTime |
            DataType.UniqueIdentifier |
            DataType.Xml |
            DataType.Binary |
            DataType.VarBinary |
            DataType.VarBinaryMax |
            DataType.Money |
            DataType.SmallMoney |
            DataType.Char |
            DataType.NVarChar |
            DataType.NVarCharMax |
            DataType.NChar |
            DataType.Text |
            DataType.NText |
            DataType.VarChar |
            DataType.VarCharMax;

        private const String TOSTRING_FORMAT = "{0}|{1}";
        private const String TOSTRING_LENGTH_FORMAT = "{0}|{1},{2}";

        public override Boolean RequiresNullableModifier(IColumnTokenDescriptor[] descriptors)
        {
            return !this.Column.DataType.IsArrayType() && !this.Column.DataType.IsStringType() && descriptors.Any(m => m.GetType() == typeof(NullableTokenDescriptor) && !String.IsNullOrEmpty(m.ToString()));
        }

        public override String ToString()
        {
            return String.Format(this.Column.Length.HasValue ? TOSTRING_LENGTH_FORMAT : TOSTRING_FORMAT, this.Column.Name, this.Column.DataType.ToString().ToLower().Replace("max", ",max"), this.Column.Length);
        }

        public override Boolean Equals(Object obj)
        {
            var that = obj as StandardDataTypeDescriptor;
            if (that == null) return false;
            else return
                this.Column.Equals(that.Column);
        }

        public override Int32 GetHashCode()
        {
            return
                this.GetType().GetHashCode() ^
                this.Column.GetHashCode();
        }
    }
}